using System;
using System.Globalization;
using System.Runtime.InteropServices;
using PickGold.Charting;

namespace PickGold.Charting.Formulas
{
	internal class VolumeIndicators : PriceIndicators
	{
		internal void AccumulationDistribution(double[][] inputValues, out double[][] outputValues)
		{
			if (inputValues.Length != 5)
			{
				throw new ArgumentException(SR.ExceptionPriceIndicatorsFormulaRequiresFourArrays);
			}
			base.CheckNumOfValues(inputValues, 4);
			outputValues = new double[][] { new double[inputValues[0].Length], new double[inputValues[0].Length] };
			double[] numArray = new double[inputValues[0].Length];
			outputValues[0][0] = inputValues[0][0];
			outputValues[1][0] = 0.0;
			for (int i = 0; i < inputValues[1].Length; i++)
			{
				outputValues[0][i] = inputValues[0][i];
				numArray[i] = (((inputValues[3][i] - inputValues[2][i]) - (inputValues[1][i] - inputValues[3][i])) / (inputValues[1][i] - inputValues[2][i])) * inputValues[4][i];
			}
			double num2 = 0.0;
			for (int j = 0; j < inputValues[1].Length; j++)
			{
				num2 += numArray[j];
				outputValues[1][j] = num2;
			}
		}

		public override void Formula(string formulaName, double[][] inputValues, out double[][] outputValues, string[] parameterList, string[] extraParameterList, out string[][] outLabels)
		{
			string name = formulaName.ToUpper(CultureInfo.InvariantCulture);
			outLabels = null;
			try
			{
				switch (name)
				{
					case "MONEYFLOW":
						this.MoneyFlow(inputValues, out outputValues, parameterList);
						return;

					case "ONBALANCEVOLUME":
						this.OnBalanceVolume(inputValues, out outputValues);
						return;

					case "NEGATIVEVOLUMEINDEX":
						this.NegativeVolumeIndex(inputValues, out outputValues, parameterList);
						return;

					case "POSITIVEVOLUMEINDEX":
						this.PositiveVolumeIndex(inputValues, out outputValues, parameterList);
						return;

					case "PRICEVOLUMETREND":
						this.PriceVolumeTrend(inputValues, out outputValues);
						return;

					case "ACCUMULATIONDISTRIBUTION":
						this.AccumulationDistribution(inputValues, out outputValues);
						return;
				}
				outputValues = null;
			}
			catch (IndexOutOfRangeException)
			{
				throw new InvalidOperationException(SR.ExceptionFormulaInvalidPeriod(name));
			}
			catch (OverflowException)
			{
				throw new InvalidOperationException(SR.ExceptionFormulaNotEnoughDataPoints(name));
			}
		}

		private void MoneyFlow(double[][] inputValues, out double[][] outputValues, string[] parameterList)
		{
			int num2;
			if (inputValues.Length != 5)
			{
				throw new ArgumentException(SR.ExceptionPriceIndicatorsFormulaRequiresFourArrays);
			}
			base.CheckNumOfValues(inputValues, 4);
			try
			{
				num2 = int.Parse(parameterList[0], CultureInfo.InvariantCulture);
			}
			catch (Exception exception)
			{
				if (exception.Message == SR.ExceptionObjectReferenceIsNull)
				{
					throw new InvalidOperationException(SR.ExceptionPriceIndicatorsPeriodMissing);
				}
				throw new InvalidOperationException(SR.ExceptionPriceIndicatorsPeriodMissing + exception.Message);
			}
			if (num2 <= 0)
			{
				throw new InvalidOperationException(SR.ExceptionPeriodParameterIsNegative);
			}
			if (inputValues[0].Length < num2)
			{
				throw new ArgumentException(SR.ExceptionPriceIndicatorsNotEnoughPoints);
			}
			outputValues = new double[][] { new double[(inputValues[0].Length - num2) + 1], new double[(inputValues[0].Length - num2) + 1] };
			double[] numArray = new double[inputValues[1].Length];
			double[] numArray2 = new double[inputValues[1].Length];
			double[] numArray3 = new double[inputValues[1].Length];
			double[] numArray4 = new double[inputValues[1].Length];
			for (int i = 0; i < inputValues[1].Length; i++)
			{
				numArray[i] = ((inputValues[1][i] + inputValues[2][i]) + inputValues[3][i]) / 3.0;
				numArray2[i] = (((inputValues[1][i] + inputValues[2][i]) + inputValues[3][i]) / 3.0) * inputValues[4][i];
			}
			for (int j = 1; j < inputValues[1].Length; j++)
			{
				if (numArray[j] > numArray[j - 1])
				{
					numArray3[j] = numArray2[j];
					numArray4[j] = 0.0;
				}
				if (numArray[j] < numArray[j - 1])
				{
					numArray4[j] = numArray2[j];
					numArray3[j] = 0.0;
				}
			}
			double num5 = 0.0;
			double num6 = 0.0;
			for (int k = num2 - 1; k < inputValues[1].Length; k++)
			{
				num5 = 0.0;
				num6 = 0.0;
				for (int m = (k - num2) + 1; m <= k; m++)
				{
					num6 += numArray4[m];
					num5 += numArray3[m];
				}
				outputValues[0][(k - num2) + 1] = inputValues[0][k];
				outputValues[1][(k - num2) + 1] = 100.0 - (100.0 / (1.0 + (num5 / num6)));
			}
		}

		private void NegativeVolumeIndex(double[][] inputValues, out double[][] outputValues, string[] parameterList)
		{
			double num;
			if (inputValues.Length != 3)
			{
				throw new ArgumentException(SR.ExceptionPriceIndicatorsFormulaRequiresTwoArrays);
			}
			base.CheckNumOfValues(inputValues, 2);
			try
			{
				num = double.Parse(parameterList[0], CultureInfo.InvariantCulture);
			}
			catch (Exception)
			{
				throw new InvalidOperationException(SR.ExceptionVolumeIndicatorStartValueMissing);
			}
			outputValues = new double[][] { new double[inputValues[0].Length], new double[inputValues[0].Length] };
			outputValues[0][0] = inputValues[0][0];
			outputValues[1][0] = num;
			for (int i = 1; i < inputValues[1].Length; i++)
			{
				outputValues[0][i] = inputValues[0][i];
				if (inputValues[2][i] < inputValues[2][i - 1])
				{
					double num3 = inputValues[1][i - 1];
					double num4 = inputValues[1][i];
					outputValues[1][i] = (((num4 - num3) / num3) * outputValues[1][i - 1]) + outputValues[1][i - 1];
				}
				else
				{
					outputValues[1][i] = outputValues[1][i - 1];
				}
			}
		}

		private void OnBalanceVolume(double[][] inputValues, out double[][] outputValues)
		{
			if (inputValues.Length != 3)
			{
				throw new ArgumentException(SR.ExceptionPriceIndicatorsFormulaRequiresTwoArrays);
			}
			base.CheckNumOfValues(inputValues, 2);
			outputValues = new double[][] { new double[inputValues[0].Length], new double[inputValues[0].Length] };
			outputValues[0][0] = inputValues[0][0];
			outputValues[1][0] = inputValues[2][0];
			for (int i = 1; i < inputValues[1].Length; i++)
			{
				outputValues[0][i] = inputValues[0][i];
				if (inputValues[1][i - 1] < inputValues[1][i])
				{
					outputValues[1][i] = outputValues[1][i - 1] + inputValues[2][i];
				}
				else if (inputValues[1][i - 1] > inputValues[1][i])
				{
					outputValues[1][i] = outputValues[1][i - 1] - inputValues[2][i];
				}
				else
				{
					outputValues[1][i] = outputValues[1][i - 1];
				}
			}
		}

		private void PositiveVolumeIndex(double[][] inputValues, out double[][] outputValues, string[] parameterList)
		{
			double num;
			if (inputValues.Length != 3)
			{
				throw new ArgumentException(SR.ExceptionPriceIndicatorsFormulaRequiresTwoArrays);
			}
			base.CheckNumOfValues(inputValues, 2);
			try
			{
				num = double.Parse(parameterList[0], CultureInfo.InvariantCulture);
			}
			catch (Exception)
			{
				throw new InvalidOperationException(SR.ExceptionVolumeIndicatorStartValueMissing);
			}
			outputValues = new double[][] { new double[inputValues[0].Length], new double[inputValues[0].Length] };
			outputValues[0][0] = inputValues[0][0];
			outputValues[1][0] = num;
			for (int i = 1; i < inputValues[1].Length; i++)
			{
				outputValues[0][i] = inputValues[0][i];
				if (inputValues[2][i] > inputValues[2][i - 1])
				{
					double num3 = inputValues[1][i - 1];
					double num4 = inputValues[1][i];
					outputValues[1][i] = (((num4 - num3) / num3) * outputValues[1][i - 1]) + outputValues[1][i - 1];
				}
				else
				{
					outputValues[1][i] = outputValues[1][i - 1];
				}
			}
		}

		private void PriceVolumeTrend(double[][] inputValues, out double[][] outputValues)
		{
			if (inputValues.Length != 3)
			{
				throw new ArgumentException(SR.ExceptionPriceIndicatorsFormulaRequiresTwoArrays);
			}
			base.CheckNumOfValues(inputValues, 2);
			outputValues = new double[][] { new double[inputValues[0].Length], new double[inputValues[0].Length] };
			outputValues[0][0] = inputValues[0][0];
			outputValues[1][0] = 0.0;
			for (int i = 1; i < inputValues[1].Length; i++)
			{
				outputValues[0][i] = inputValues[0][i];
				double num = inputValues[1][i - 1];
				double num2 = inputValues[1][i];
				outputValues[1][i] = (((num2 - num) / num) * inputValues[2][i]) + outputValues[1][i - 1];
			}
		}

		public override string Name
		{
			get
			{
				return SR.FormulaNameVolumeIndicators;
			}
		}
	}
}

